package org.cying.main.controller;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpStatus;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.cying.main.dao.Querys;
import org.cying.main.domain.SampleResult;
import org.cying.main.domain.Student;
import org.cying.main.domain.TimeState;
import org.cying.main.feign.ClientFeignSign;
import org.cying.main.feign.ClientFeignStudent;
import org.cying.main.handler.ClientFlowHandler;
import org.cying.main.handler.GlobalFlowHandler;
import org.cying.main.util.ClientUtils;
import org.cying.main.util.Method;
import org.cying.main.util.RsaUtil;
import org.cying.main.util.Token;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Slf4j
@RefreshScope
@RestController
@RequestMapping(value = "/client")
public class ClientController {

    @Resource
    private ClientFeignSign signSer;

    @Resource
    private ClientFeignStudent stuSer;

    @Resource
    private Querys query;

    @Value("${cying.private-key}")
    private String privateKey;

    private static Token token = Token.getInstance();
    private static TimeState STATE;

    /**
     * 验证 cookie
     * @param request 请求头
     * @return 验证结果
     */
    @GetMapping(value = "/auth/cookie")
    @SentinelResource(
        value = "auth-cookie",
        blockHandlerClass = ClientFlowHandler.class,
        blockHandler = "checkHandler"
    )
    public SampleResult<Student> authCookie(
        HttpServletRequest request
    ) {
        String uid = ClientUtils.checkCookie(request.getCookies(), "id");
        Long sid = Long.valueOf(RsaUtil.dencrypt(uid, privateKey));
        if (sid == null) {
            return new SampleResult<>("/client/auth/cookie", HttpStatus.HTTP_NOT_ACCEPTABLE, null, "尚未登陆");
        } else {
            SampleResult<Student> stu = stuSer.getStuBySid(uid);
            String json = JSON.toJSONString(stu.getData());
            Student student = JSONObject.parseObject(json, Student.class);
            return new SampleResult<>("/client/auth/cookie", HttpStatus.HTTP_OK, student, "登陆成功");
        }
    }

    /**
     * 与现有令牌进行匹配
     * @param token 待匹配的令牌
     * @return 匹配结果
     */
    @GetMapping(value = "/auth/token")
    @SentinelResource(
        value = "auth-token",
        blockHandlerClass = ClientFlowHandler.class,
        blockHandler = "checkTokenHandler"
    )
    public SampleResult<Boolean> authToken(
        @RequestParam("token") Integer token
    ) {
        return token.equals(ClientController.token.getToken())
                ? new SampleResult<>("/client/auth/token", HttpStatus.HTTP_OK, true)
                : new SampleResult<>("/client/auth/token", HttpStatus.HTTP_NOT_ACCEPTABLE, false);
    }

    /**
     * 查询所有学院
     * @return 查询结果
     */
    @GetMapping(value = "/get/colleges")
    @SentinelResource(
            value = "get-colleges",
            blockHandlerClass = GlobalFlowHandler.class,
            blockHandler = "flowHandler"
    )
    public SampleResult<List<String>> getColleges() {
        return new SampleResult<>("/stu/get/colleges", HttpStatus.HTTP_OK, query.getColleges());
    }

    /**
     * 获取令牌、时间段提示、当前待签到人员
     * 如遇执勤时间段更新, 应通知相应微服务进行数据更新
     * @return 处理结果
     */
    @GetMapping(value = "/get/token")
    @SentinelResource(
        value = "get-token",
        blockHandlerClass = GlobalFlowHandler.class,
        fallback = "defaultFallback",
        blockHandler = "flowHandler"
    )
    public synchronized SampleResult<List<Object>> getToken() {
        TimeState time = Method.getTime();
        if (STATE == null || STATE.getFlag() != time.getFlag()) {
            if (STATE != null) {
                signSer.postRecord(STATE.getInfo());
            }
            signSer.alterRefresh();
            STATE = time;
        }
        token.setToken(RandomUtil.randomInt(100000, 999999));
        SampleResult<Map<Long, Student>> dutyList = signSer.getDuty();
        List<Object> list = Arrays.asList(time, token, dutyList.getData());
        return new SampleResult<>("/client/get/token", 200, list);
    }

}


